﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Collections;
using System.Diagnostics;
namespace Lon.IO.Ports
{
    public class BusOpt<T> : IBusOpt<T>
    {
        AutoResetEvent rxEvent = new AutoResetEvent(false);
        Queue<T> dataQueue = new Queue<T>(5000);
        List<IListener<T>> listenerList = new List<IListener<T>>(100);
        Stopwatch sw = new Stopwatch();
        public BusOpt()
        {
            Thread rxThread = new Thread(new ThreadStart(RxProc));
            rxThread.IsBackground = true;
            rxThread.Start();
        }
        public bool Write(T val)
        {
            lock (dataQueue)
            {
                if (dataQueue.Count >= 4000) return false;
                dataQueue.Enqueue(val);
            }
            rxEvent.Set();
            return true;
        }
        public bool AddListener(IListener<T> lisenter)
        {
            lock (((ICollection)listenerList).SyncRoot)
            {
                listenerList.Add(lisenter);
            }
            return false;
        }
        public bool DelListener(IListener<T> lisenter)
        {
            lock (((ICollection)listenerList).SyncRoot)
            {
                listenerList.Remove(lisenter);
            }
            return true;
        }
        private void RxProc()
        {
            try
            { 
               
                while (true)
                {
                    rxEvent.WaitOne();
                    FillListenter();
                }
            }
            catch (System.Exception ex)
            {
                Trace.WriteLine("Error" + ex.Message + ex.Source + ex.StackTrace + ex.InnerException);
            }

        }

        private void FillListenter()
        {
             T val=default(T);
            lock (dataQueue)
            {
                while (dataQueue.Count > 0)
                {
                    val = dataQueue.Dequeue();
                    lock (((ICollection)listenerList).SyncRoot)
                    {

                        foreach (IListener<T> lisener in listenerList)
                        {
                            if (lisener != null)
                            {

                                lisener.Write(val);
                            }
                        }
                    }
                }

            }
        }
    }
}
